20. Exercise: Schedule Background Work
L9 43 Running Work SC
It's time to use the Worker you defined in the last exercise.
You'll do this exercise it in two parts. In the first part, you'll add code to the DevByteApplication class to schedule your RefreshDataWork to run once a day. Then, in the second part, you'll define constraints to prevent running work when there's no network or the device is low on battery.
1. Create a coroutine scope to use for your application:
Open DevByteApplication. Add a coroutine scope variable, applicationScope, which uses Dispatchers.Default:
val applicationScope = CoroutineScope(Dispatchers.Default)
2. Create an initialization function that does not block the main thread:
It's important to note that WorkManager.initialize should be called from inside onCreate without using a background thread to avoid issues caused when initialization happens after WorkManager is used.
Create the function delayedInit() that uses the applicationScope you defined above. It should call a function (which you haven't created yet) called setupRecurringWork().
private fun delayedInit() = applicationScope.launch {
setupRecurringWork()
}
3. Add a call to delayedInit() in onCreate().
4. Make a PeriodWorkRequest:
Create a setupRecurringWork() function. In it, define a repeatingRequest variable that uses a PeriodicWorkRequestBuilder to create a PeriodicWorkRequest for your RefreshDataWorker. It should run once every day.
private fun setupRecurringWork() {
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
}
5. Schedule the work as unique:
Get an instance of WorkManager and call enqueueUniquePeriodicWork to schedule the work.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
6. Create a unique identifier for your work:
In RefreshDataWorker.kt, create a companion object and define a work name that can be used to uniquely identify this worker.
companion object {
const val WORK_NAME = "RefreshDataWorker"
}
7. Build and run your app to make sure everything's on track.
So far so good! You've created a work request, but now you have to tell WorkManager under what conditions to run the work. The next video will show you how to create constraints so work will run only when you want it to.
L9 44 Work Constraints SC
1. Define constraints:
Open DevByteApplication.kt. In setupRecurringWork(), use a Builder to define constraints In setupRecurringWork(). Define constraints to prevent work from occurring when there is no network access or the device is low on battery.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}.build()
**2. Add the constraints: **
Finally, add the constraint to the repeatingRequest definition.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
If you want to start at this step, you can download this exercise code from: Step.08-Exercise-Schedule-Background-Work.
You will find plenty of //TODO comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.08-Solution-Schedule-Background-Work or using this git diff
Task Description:
Complete the following steps to schedule work to run in the background.
Task Feedback:
Amazing! Your users are going to really love this new pre-fetch. Thank you so much!
Reference documentation